/*
 ╭──────────╮
╭│    ╭────╮
││    ╰────╯
││          │
╰│ ┌─────┌  │
 ╰─╯     ╰─╯ Lin.Meng. was a hardworking programmer.
                   No one can despise him.
                   And we have to bless his program without BUG!~    And program burned successfully!~
                   Bug,fuck out!!!!!!
                   :)
*/
/*                 .::::.
                 .::::::::.
                :::::::::::
             ..:::::::::::'
          '::::::::::::'
            .::::::::::
       '::::::::::::::..        女神助攻,程序烧写成功
            ..::::::::::::.     永不宕机,代码无bug
          ``::::::::::::::::
           ::::``:::::::::'        .:::.
          ::::'   ':::::'       .::::::::.
        .::::'      ::::     ..::::::'::::.
       .:::'       :::::  ..::::::::' ':::::.
      .::'        :::::..::::::::'      ':::::.
     .::'         ::::::::::::::'         ``::::.
 ...:::           ::::::::::::'              ``::.
```` ':.          ':::::::::'                  ::::..
                   '.:::::'                    ':'````..
*/
/*                   _ooOoo_
                    o8888888o
                   88\" . \"88
                   (|  $_$  |)    $
                    O\  =  /O
                ____/`---'\\____
              .'  \\\\|     |//  `.
             /   \\|||  :  |||//  \\
            /  _||||| -:- |||||-  \\
            |   | \\\\\\  -  /// |   |
            | \\_|  ''\\---/''  |   |
            \\  .-\\__  `-`  ___/-. /
          ___`. .'  /--.--\\  `. . ___
        .\"\" '<  `.___\\_<|>_/___.'  >'\"\".
      | | :  `- \\`.;`\\ _ /`;.`/ - ` : | |
      \\  \\ `-.   \\_ __\\ /__ _/   .-` /  /
========`-.____`-.___\\_____/___.-`____.-'========
                     `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


   佛祖保佑       永不宕机     永无BUG    程序烧写成功 */
#include <ioCC2530.h>               //引用 CC2530 头文件
#include <string.h>                 //引用新头文件，此头文件关系本次代码写法：uchar等等
#define SW1 P1_2                    //宏定义，如下是LED宏定义
#define LED1 (P1_0)                 //宏定义，LED1，简单好写。
#define LED2 (P1_1)                 //宏定义，LED2，简单好写.
#define DATABUFF_SIZE 3             //数据缓冲区大小，在第五单元PDF
#define uchar unsigned char
unsigned int t3_Count=0;            //定时器3溢出次数计数。
uchar buff_RxDat[DATABUFF_SIZE+1];
uchar chat = 0;                     //数据缓冲区 + 下标


#pragma vector = T3_VECTOR
__interrupt void T3_INT(void)
{
  IRCON = 0x00;                     //清理中断标志，也可以通过硬件自清理。这一行去查看ioCC2530的Interrupt Flags 4
  t3_Count++;                       //t3，使用int整数型。
}


void initUART0(void)
{
  PERCFG=0x00;
  P0SEL=0x3c;                       //启动P0.2 P0.3 P0.4 P0.5作为外设IO口。第五单元PDF有详细介绍。
  U0CSR|=0x80;                      //11110000 UART mode+禁止接收器+SPI 从
  U0UCR|=0x80;                      //11110000 清除单元 +禁止流控制+奇校验+8位传送禁9位+1停止位低电平
  U0BAUD=216;                       //U0BAUD.BAUD_M = 216 
  U0GCR=10;                         //U0GCR.BAUD_M = 10 如上对应CC2530串行通信波特率 设置为57600 误差0.03%
  UTX0IF=0;                         //清零UART0TX中断标志
  EA = 1;                           //使能中断
  U0CSR |= 0x40;                    //允许接收,这句话尤其重要！
}

void receive_handler(void)
{
  unsigned char onoff=0;            //LED 灯的开关状态
  unsigned char c;
  c = U0DBUF;                       //读取收取到的字节，unsigned char为无符号整数型，本次需要用到这类。而不是直接char。
                                    //         char         = -128~127
                                    //unsigned char = uchar = 0~255
                                    //c = USART 0 Receive/Transmit Data Buffer 在ioCC2530.h头文件Interrupt Flags 4
  if(c == '#')
  {
    buff_RxDat[0]=c;
    chat=0;
  }
  else if(buff_RxDat[0]=='#')
  {
    chat++;
    buff_RxDat[chat]=c;
  }
  if(chat>=2)
  {
    onoff=buff_RxDat[2]-0x30;
    switch(buff_RxDat[1])
    {
      case '1':
        LED1=onoff;
        break;
      case '2':
        LED2=onoff;
        break;
    }
  }
  if(chat>=2)
  {
    for(int i=0;i<=DATABUFF_SIZE;i++)
    {                               //清空接收到的字符串
      buff_RxDat[i]=(unsigned char)0;
      chat = 0;                     //尤其重要！请查看注释以获取相关信息！
    }
  }
}

void UART0SendByte(unsigned char c)
{
  U0DBUF = c;                       //将要发送的 1 字节数据写入 U0DBUF
  while (!UTX0IF);                  //等待 TX 中断标志，即 U0DBUF 就绪
  UTX0IF = 0;                       //清零 TX 中断标志
}

void UART0SendString(unsigned char *str)
{
  while(*str != '\0')
  {
    UART0SendByte(*str++);          //发送字节数据
  }
}

void initTimer1()
{
  CLKCONCMD &= 0x80;                //时钟速度设置为 32MHz
  T3CCTL0 =50000 & 0xFF;            //把 50000 的低 8 位写入 T3CCTL0 /*  Timer 3 Channel 0 Capture/Compare Control          */
  T3CC0 =((50000 & 0xFF00) >> 8);   //把 50000 的高 8 位写入 T3CC0   /*  Timer 3 Channel 0 Capture/Compare Value            */
  EA = 1;                           //使能全局中断
  T3CTL |= 0xE0;                    //定时器3 时钟频率128分频 设置最大计数值在此设置。
                                    //推一下我的计算方式吧，因为我这一次跟老师不一样。
                                    //首先，128分频,128/16000000*N=0.5S,N=62500
  T3IE = 1;                         //使能定时器3      总中断                                  
  T3CCTL0 |= 0x08;                  //使能定时器3通道1 溢出中断
  T3CCTL0 &= ~0x03;                 //定时器3通道1 采用 自由mode
                                    //00->0xff 62500/255=245次。此时245次为0.5秒。
  T3CTL |= 0x10;                    //启动 关键code 全局启动
}

/***************************************************************************************************************
本次1.6.2020.1229.5-end Code版本，代码和写法均来自第五单元.pdf和CC2530中文数据手册完全版和头文件.
                                    第五单元.pdf                 
                                    ioCC2530.h                   C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.0\8051\bin
                                    万众瞩目的本次版本，终于更新了。
                                    本次代码本体功能为：使用T3计时器和UARP进行串口通信，与此同时支持#10 #11 #20 #21来管理LED1 LED2
                                    总的来说，传仓和接收代码在蓝板上运行的很成功。响应能力其实还有待考究。
                                    由于T3计时器我希望在程序运行时，能够反馈给我们而不是通过sscom。所以我占用了LED2闪烁。所以能使用的发送命令也就剩下了#10 #11
                                    #10 LED1关闭
                                    #11 LED1开启
                                    #20 LED2关闭 （最好别用）
                                    #21 LED2开启 （同上）
                                    这里有一些代码与PDF不会很相同，但都能带上我对于这里的解释，如下：
                                    buff_RxDat[i]=(unsigned char)0; PDF为 buff_RxDat[i]=(uchar)NULL;
                                    这里我做个个人解释吧，由于我们传仓时，NULL其实是没给他定义数型的。那么，我们如果想要表达uchar空值，我们可以投机取巧选择0。
                                    uchar chat = 0;                 PDF为 uchar uIndex = 0;
                                    chat，意为聊天，人机对话罢了。其实这个是影响后面程序的，大家可以留意。不过能用何乐而不为呢？
                                    （虽然我已经写了用了unsigned char = uchar这个东西，但是我还是希望大家能省就省吧~）
                                    最后我要说的就是U0CSR |= 0x40;了，这句话在timer函数里尤其重要。
                                    然后，请大家尽情享用这份代码吧~把代码远程git下来，开始你们的C之旅吧！
                                    欢迎大家认真使用，本代码已经同步至GITEE仓库，遵守BY-NC-SA4.0协议，使用转载请署名。
***************************************************************************************************************/

void main(void) 
{
  /*LED1 LED2设置普通IO输出口完毕*/
  LED1 = 0;
  LED2 = 0;
  P1SEL &= ~0x03;                   //设置P1.0和P1.1为普通IO口。P1.0 P1.1为LED
  P1DIR |= 0x03;                    //设置P1.0和P1.1为输出口。  P1.0 P1.1为LED
  CLKCONCMD &= 0x80;                //时钟速度设置为 32MHz
  /*调用函数 initTimer1 initUART0 也已经完成初始化设置*/
  initTimer1();                     //初始化如上函数，EA全局使能中断可以在这里写。
  initUART0();                      //初始化如上上函数
  
  while(1)
  { 
    //设置发送已经设定好的数据,目前已经注释,无需使用**
    
    if(t3_Count>=1470)              //3秒，1秒=490
    {
      //LED1 = 1;
      UART0SendString("CC2530在线 ");
      //LED1 = 0;
      LED2 = 1;
      UART0SendString("CC2530working.\n");
      LED2 = 0;
      t3_Count = 0;
    }
    
    if(URX0IF)
    {
      URX0IF = 0;//清中断标志
      receive_handler(); //调用接收数据后处理函数
    }
  }
}

